// Copyright (C) 2025, ZWSOFT Co., LTD.(Guangzhou)
// Licensed under the MIT License. See LICENSE in the project root for license information.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using TestClient.Domain;

namespace TestClient.ViewModel
{
    public partial class InquireTestViewModel : PageViewModelBase
    {
        [ObservableProperty]
        private double inquiredArea;
        [ObservableProperty]
        private double inquiredPerimeter;
        [ObservableProperty]
        private double inquiredWeight;
        [ObservableProperty]
        private string inquiredCentroid = "";
        [ObservableProperty]
        private double inquiredCurveLen;
        [ObservableProperty]
        private string inquiredActiveDocName = "";
        [ObservableProperty]
        private string inquiredActiveDocPath = "";
        [ObservableProperty]
        private string inquiredActiveDocType = "";
        [ObservableProperty]
        private string inquiredStartPoint = "";
        [ObservableProperty]
        private string inquiredEndPoint = "";

        [ObservableProperty]
        private string gxSurfaceId = "";
        [ObservableProperty]
        private string gxStartPointId = "";
        [ObservableProperty]
        private string gxHintPointId = "";
        [ObservableProperty]
        private string gxInquiredType = "";
        [ObservableProperty]
        private string gxInquiredGeneratrix = "";

        [ObservableProperty]
        private string surfaceId = "";
        [ObservableProperty]
        private string curveId = "";
        [ObservableProperty]
        private double density = 2.7;

        public IAsyncRelayCommand SelectSurfaceCommand { get; }
        public IAsyncRelayCommand SelectCurveCommand { get; }
        public IAsyncRelayCommand InquireCommand { get; }
        public IAsyncRelayCommand InquireCurveCommand { get; }
        public IAsyncRelayCommand InquireActiveDocCommand { get; }

        public IAsyncRelayCommand SelectGxSurfaceCommand { get; }
        public IAsyncRelayCommand SelectGxPoint1Command { get; }
        public IAsyncRelayCommand SelectGxPoint2Command { get; }
        public IAsyncRelayCommand InquireSurfaceGeneratrixCommand { get; }

        public InquireTestViewModel(
            VFAdapterWrapper wrapper,
            ISnackNotifyService notifyService)
            : base(wrapper, notifyService)
        {
            SelectSurfaceCommand = CreateAsyncRpcCommand(SelectSurface);
            SelectCurveCommand = CreateAsyncRpcCommand(SelectCurve);
            InquireCommand = CreateAsyncRpcCommand(Inquire);
            InquireCurveCommand = CreateAsyncRpcCommand(InquireCurve);
            InquireActiveDocCommand = CreateAsyncRpcCommand(InquireActiveDoc);

            SelectGxSurfaceCommand = CreateAsyncRpcCommand(SelectGxSurfaceAsync);
            SelectGxPoint1Command = CreateAsyncRpcCommand(SelectGxPoint1Async);
            SelectGxPoint2Command = CreateAsyncRpcCommand(SelectGxPoint2Async);
            InquireSurfaceGeneratrixCommand = CreateAsyncRpcCommand(InquireSurfaceGeneratrixAsync);
        }

        private async Task SelectSurface()
        {
            EnsureConnected();
            SurfaceId = await ViewModelHelpers.SelectEnt(Wrapper, "Surface");
        }

        private async Task SelectCurve()
        {
            EnsureConnected();
            CurveId = await ViewModelHelpers.SelectEnt(Wrapper, "Curve");
        }

        private async Task Inquire()
        {
            EnsureConnected();
            var (area, perimeter, weight, centroid) = await Task.Run(() =>
            {
                var area = Wrapper.SurfaceArea(SurfaceId);
                var perimeter = Wrapper.SurfacePerimeter(SurfaceId);
                var weight = Wrapper.SurfaceWeight(SurfaceId, Density);
                var centroid = Wrapper.GravityOfSurface(SurfaceId);
                return (area, perimeter, weight, centroid);
            });
            InquiredArea = area;
            InquiredPerimeter = perimeter;
            InquiredWeight = weight;
            InquiredCentroid = centroid.ToString();
        }

        private async Task InquireCurve()
        {
            EnsureConnected();
            var (length, p0, p1) = await Task.Run(() =>
            {
                var len = Wrapper.GetCurveLength(CurveId);
                var (p0, p1) = Wrapper.GetCurveEndPoints(CurveId);
                return (len, p0, p1);
            });
            InquiredCurveLen = length;
            InquiredStartPoint = p0.ToString();
            InquiredEndPoint = p1.ToString();
        }

        private async Task InquireActiveDoc()
        {
            EnsureConnected();
            (InquiredActiveDocName, InquiredActiveDocPath, InquiredActiveDocType) = await Task.Run(() =>
            {
                var name = Wrapper.GetActiveDocumentName();
                var path = Wrapper.GetActiveDocumentPath();
                var type = Wrapper.GetActiveDocumentType();
                return (name, path, type);
            });
        }

        private async Task SelectGxSurfaceAsync()
        {
            EnsureConnected();
            GxSurfaceId = await ViewModelHelpers.SelectEnt(Wrapper, "Surface");
        }

        private async Task SelectGxPoint1Async()
        {
            EnsureConnected();
            GxStartPointId = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
        }

        private async Task SelectGxPoint2Async()
        {
            EnsureConnected();
            GxHintPointId = await ViewModelHelpers.SelectEnt(Wrapper, "Point");
        }

        private async Task InquireSurfaceGeneratrixAsync()
        {
            EnsureConnected();
            var (faceType, generatrix) = await Task.Run(() =>
            {
                var p1 = Wrapper.GetPointCoord(GxStartPointId);
                var p2 = Wrapper.GetPointCoord(GxHintPointId);
                return Wrapper.TestTypeOfSurfaceAndGetGeneratrixVector(GxSurfaceId, p1, p2);
            });

            switch (faceType)
            {
                case 0:
                    GxInquiredType = "Other";
                    GxInquiredGeneratrix = "N/A";
                    break;
                case 1:
                    GxInquiredType = "Cylinder";
                    GxInquiredGeneratrix = generatrix.ToString();
                    break;
                case 2:
                    GxInquiredType = "Cone";
                    GxInquiredGeneratrix = generatrix.ToString();
                    break;
                case 3:
                    GxInquiredType = "Plane";
                    GxInquiredGeneratrix = "N/A";
                    break;
            }
        }
    }
}
